#include "common_lib/log.h"

using namespace common_lib;

SpdLog *SpdLog::unique_instance = nullptr;
pthread_mutex_t SpdLog::mutex;

void SpdLog::Init()
{
    rotating_type_log_size_ = 40;
    rotation_type_log_num_ = 2;
    log_level_ = spdlog::level::trace;
    type_ = LOG_TYPE::ROTATING;
}

SpdLog *SpdLog::Instance()
{
    if (NULL == unique_instance)
    {
        pthread_mutex_lock(&mutex);
        if (NULL == unique_instance)
        {
            unique_instance = new SpdLog;
        }
        pthread_mutex_unlock(&mutex);
    }
    
    return unique_instance;
}

void SpdLog::InitSpdLog(std::string path, std::string node_name)
{
    std::string file_name = GenerateFileName(path, node_name);

    printf("SpdLog::InitSpdLog() --> log name: %s\n", file_name.c_str());

    //设置日志等级 低于此级别不输出
    spdlog::set_level(static_cast<spdlog::level::level_enum>(log_level_));
    // 设置日志格式
    // spdlog::set_pattern("[%Y-%m-%d %H:%M:%S.%e][%l]%v");//[时间][日志等级][阅读对象]:日志描述 [故障码] [故障来源]
    //                                                         //[时间][日志等级][索引标识]:数据描述:数据值
    spdlog::set_pattern("%+");
    //设置日志为异步日志，不带滚动，日志文件会一直写入
    if (type_ == LOG_TYPE::BASIC)
        ptr_logger_ = spdlog::basic_logger_mt<spdlog::async_factory>(node_name, file_name);
    else if (type_ == LOG_TYPE::ROTATING)
        ptr_logger_ = spdlog::rotating_logger_mt<spdlog::async_factory>(node_name, file_name, rotating_type_log_size_ * 1024 * 1024, rotation_type_log_num_);
    else if (type_ == LOG_TYPE::DAILY)
    {
        ptr_logger_ = spdlog::daily_logger_mt<spdlog::async_factory>(node_name, file_name,0,0);//00:00
    }
    spdlog::set_default_logger(ptr_logger_);
    //当遇到错误级别以上的立刻刷新到日志
    ptr_logger_->flush_on(spdlog::level::err);
    spdlog::color_mode::always;
    //每三秒刷新一次
    spdlog::flush_every(std::chrono::seconds(30));//缓存写入硬盘时间,不是写入频率

    auto tmp = std::string("logger");
    auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
	auto rotating_file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>("./log/log1.log", 1048576 * 5, 3);
	std::vector<spdlog::sink_ptr> sink_vector{console_sink, rotating_file_sink};
	auto temp_logger = std::make_shared<spdlog::logger>(tmp, sink_vector.begin(), sink_vector.end());
	spdlog::register_logger(temp_logger);
}

void SpdLog::EndLog()
{
    spdlog::shutdown();
}

SpdLog::SpdLog()
{
    Init();
}

SpdLog::~SpdLog()
{
    delete unique_instance;
    EndLog();
}

void SpdLog::SetType(LOG_TYPE type)
{
    type_ = type;
}
void SpdLog::SetLevel(int level)
{
    log_level_ = level;
}

void SpdLog::SetLogSize(float size,  float num)
{
    rotating_type_log_size_ = size;
    rotation_type_log_num_ = num;
}

std::string SpdLog::GenerateFileName(std::string path, std::string node_name)
{
    time_t local_time;
    time(&local_time);
    struct tm *cur_time = localtime(&local_time);

    /* 通过时间命名日志文件 */
    char filename[200];
    strftime(filename, 100, "%Y-%m-%d_%H-%M-%S.log", cur_time);

    /* 判断日志路径是否存在，若不存在，则创建 */
    /* Check if the input log path exists, if not, create the path */
    if (access(path.c_str(), F_OK) != 0)
    {
        mkdir(path.c_str(), S_IRWXU);
    }

    /* 记录日志创建时间，在通过时间长度控制日志文件大小时，该成员变量会被使用 */
    logger_create_time = local_time;

    return path + "/" + node_name + "_" + std::string(filename);
}